package com.ymx.darling.bean.sql;

import com.ymx.darling.build.mapper.dynamic.DynamicContext;
import com.ymx.darling.expression.ExpressionAccess;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 最终绑定sql的实例
 *
 * @author 爱Java的小于
 */
public class BoundSql {
    private String sql; // 解析后的sql
    private Object parameterObject; // 绑定前的参数对象
    private List<String> parameterMappings; // 参数映射
    private List<Object> bindParameters; // 绑定后的参数列表
    private List<Object> leftParameters = new ArrayList<>(); // 参数绑定后的前置参数列表
    private List<Object> rightParameters = new ArrayList<>(); // 参数绑定后的后置参数列表

    public BoundSql(String sql, Object parameterObject, List<String> parameterMappings) {
        this.sql = sql;
        this.parameterObject = parameterObject;
        this.parameterMappings = parameterMappings;
    }

    public BoundSql(String sql, List<Object> bindParameters) {
        this.sql = sql;
        this.bindParameters = bindParameters;
    }

    public BoundSql(String sql) {
        this.sql = sql;
        this.bindParameters = Collections.emptyList();
    }

    public void setSql(String sql) {
        this.sql = sql;
    }

    public List<Object> getLeftParameters() {
        return leftParameters;
    }

    public List<Object> getRightParameters() {
        return rightParameters;
    }

    public List<String> getParameterMappings() {
        return parameterMappings;
    }

    public String getSql() {
        return sql;
    }

    /**
     * 获取参数实例
     * @return 参数实例
     */
    public Object getParameterObject() {
        return parameterObject instanceof DynamicContext ? ((DynamicContext)parameterObject).getContext() : parameterObject;
    }

    /**
     * 获取参数绑定前的SQL
     * @return Sql
     */
    public String getParameterBeforeBindSql() {
        if (this.parameterMappings == null || this.parameterMappings.isEmpty()) {
            return this.sql;
        }
        StringBuilder sqlBuilder = new StringBuilder();
        String sql = this.sql;
        for (int i = 0, placeholderIndex = 0, len = sql.length(); i < len; ++i) {
            char c = sql.charAt(i);
            if (c == '?') {
                sqlBuilder.append(String.format("#{%s}", this.parameterMappings.get(placeholderIndex++)));
            } else {
                sqlBuilder.append(c);
            }
        }
        return sqlBuilder.toString();
    }

    public List<Object> getBindParameters() {
        return bindParameters;
    }

    /**
     * 获取处理后的完整SQL语句和最终参数值
     * (包含原始参数、动态添加的前后置参数)
     */
    public void bindSqlParameter() {
        // 绑定后的参数列表
        List<Object> paramList = this.bindParameters != null
                ? this.bindParameters
                : new ArrayList<>();
        // 设置前置参数
        if (!this.leftParameters.isEmpty()) {
            paramList.addAll(0, this.leftParameters);
        }
        // 绑定参数
        if (this.parameterMappings != null) {
            ExpressionAccess parameterAccess = new ExpressionAccess(this.parameterObject);
            for (String paramPlaceholder : this.parameterMappings) {
                Object paramValue = parameterAccess.getValue(paramPlaceholder);
                paramList.add(paramValue);
            }
        }
        // 设置后置参数
        if (!this.rightParameters.isEmpty()) {
            paramList.addAll(this.rightParameters);
        }

        this.bindParameters = paramList;
        this.leftParameters = new ArrayList<>();
        this.rightParameters = new ArrayList<>();
    }
}
